package pe.gob.servir.apps.censodirectivo.ejb.dao;

import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import javax.ejb.EJB;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

import oracle.jdbc.OracleTypes;

import org.apache.log4j.Logger;
import org.hibernate.Session;
import org.hibernate.jdbc.Work;

import pe.gob.servir.apps.censodirectivo.common.constantes.Constantes;
import pe.gob.servir.apps.censodirectivo.common.dao.AbstractJPABaseDAO;
import pe.gob.servir.apps.censodirectivo.common.util.Utilitario;
import pe.gob.servir.apps.censodirectivo.excepcion.DAOExcepcion;
import pe.gob.servir.apps.censodirectivo.model.bean.MensajeRespuesta;
import pe.gob.servir.apps.censodirectivo.model.bean.Organo;
import pe.gob.servir.apps.censodirectivo.persistence.entity.TblOrgano;

/**
 * Session Bean implementation class AreaInteresDAO
 */
@Stateless
public class OrganosDAO extends AbstractJPABaseDAO<TblOrgano> implements OrganosDAOLocal {

	private static final Logger log = Logger.getLogger(OrganosDAO.class);
	
	@PersistenceContext(unitName = "persistenceUnitCenso")
	EntityManager entityManager;
	
	@EJB
	private ConsumirProcedimientoDAOLocal consumirProcedimientoDAOLocal;

	@Override
	protected EntityManager getEntityManager() {
		return entityManager;
	}

    public OrganosDAO() {
    	super(TblOrgano.class);
    }

	@Override
	public List<Organo> filtrarListaOrganos(final long entidadId,
			final String nombreOrgano) throws DAOExcepcion {
		
		Session session = entityManager.unwrap(Session.class);
		final List<Organo> listaOrganoSP = new ArrayList<Organo>();
		session.doWork(new Work() {
		
			@Override
			public void execute(Connection connection) throws SQLException {
				CallableStatement callableStatement = null;
				ResultSet resultset = null;

				try {
					callableStatement = connection.prepareCall(Constantes.SP_CONSULTAR_ORGANOS);
					callableStatement.setLong("E_ENTIDAD_ID",entidadId);
					callableStatement.setString("E_ORGANO", nombreOrgano);
					callableStatement.registerOutParameter("S_CURSOR", OracleTypes.CURSOR);
					callableStatement.registerOutParameter("S_ID_ERROR", OracleTypes.INTEGER);
					callableStatement.registerOutParameter("S_DES_ERROR", OracleTypes.VARCHAR);
					callableStatement.execute();
					resultset = (ResultSet) callableStatement.getObject("S_CURSOR");//Cursor
					while (resultset.next()) {
						Organo organo = new Organo();
						organo.setOrganoId(resultset.getLong("ORGANO_ID"));
						organo.setNombreOrgano(resultset.getString("ORGANO"));
						organo.setNombreEntidad(resultset.getString("NOMB_ENTIDAD"));
						organo.setEstadoRegistro(resultset.getString("ESTADO_REGISTRO"));
						organo.setEntidadId(resultset.getLong("ENTIDAD_ID"));
						listaOrganoSP.add(organo);
					}
					
				} catch(SQLException e){
					log.error("SQLException : ", e);
					throw e;
				} catch (Exception e) {
					log.error("Exception : ", e);
					throw e; 
				} finally {
					Utilitario.cerrarConexiones(resultset, callableStatement);
				}
			}
		});
		return listaOrganoSP;
		
	}
	
    @Override
	public MensajeRespuesta registrarOrgano(final long entidadId,
			final String organo, final String usuario) throws DAOExcepcion {
    	
		log.info("Parametros Entrada [organo]: " + organo);
		log.info("Parametros Entrada [entidadId]: " + entidadId);
		log.info("Parametros Entrada [usuario]: " + usuario);

		Session session = entityManager.unwrap(Session.class);
		final MensajeRespuesta mensajeRespuesta = new MensajeRespuesta();
		try {
			session.doWork(new Work() {
				@Override
				public void execute(Connection connection) throws SQLException {
					CallableStatement callableStatement = null;
					try {
						connection.setAutoCommit(false);
						callableStatement = connection.prepareCall(Constantes.SP_INSERTAR_ORGANOS);
						callableStatement.setString("E_ORGANO", organo);
						callableStatement.setLong("E_ENTIDAD_ID",entidadId);
						callableStatement.setString("E_USUARIO", usuario);
						callableStatement.registerOutParameter("S_ID_ERROR",OracleTypes.INTEGER);
						callableStatement.registerOutParameter("S_DES_ERROR",OracleTypes.VARCHAR);
						callableStatement.registerOutParameter("S_DES_ERROR_INFO",OracleTypes.VARCHAR);
						callableStatement.execute();
						
						log.info("Se ejecuto exitosamente el SP.");
						int codigoError = callableStatement.getInt("S_ID_ERROR");
						String mensajeError = callableStatement.getString("S_DES_ERROR");
						String mensajeErrorInfo = callableStatement.getString("S_DES_ERROR_INFO");
						
						log.info("Parametros Salida [codigoError]: " + codigoError);
						log.info("Parametros Salida [mensajeError]: " + mensajeError);
						
						mensajeRespuesta.setCodigoError(String.valueOf(codigoError));
						mensajeRespuesta.setMensajeError(mensajeError);
												
						if (callableStatement.getInt("S_ID_ERROR") == 0) {
							log.info("Se actualizo el directivo con exito en BD.");
							connection.commit();
						} else {
							log.info("No se pudo actualizar los datos en BD. " + mensajeErrorInfo);
							throw new SQLException();
						}
						
					} catch (SQLException e) {
						if (mensajeRespuesta.getMensajeInfo() != null){
							log.error("SQLException : " + mensajeRespuesta.getMensajeInfo());
						}
						connection.rollback();
						throw e;
					} catch (Exception e) {
						log.error("Exception : " + e.getMessage(), e);
						connection.rollback();
						throw e;
					} finally {
						Utilitario.cerrarCallableStatement(callableStatement);
					}
				}
			});
		}  catch (Exception e) {
			if (mensajeRespuesta.getCodigoError() == null) {
				String mensajeError = consumirProcedimientoDAOLocal.consultarMensaje(Constantes.CODIGO_MSJ_ERROR_DB);
				throw new DAOExcepcion(Constantes.CODIGO_MSJ_ERROR_DB, mensajeError);
			}
//			throw new DAOExcepcion(mensajeRespuesta.getCodigoError(), mensajeRespuesta.getMensajeError());
		}
		return mensajeRespuesta;

	}
    
    @Override
	public MensajeRespuesta actualizarOrgano(final long organoId, final long entidadId,
			final String organo, final String usuario, final String estadoRegistro) throws DAOExcepcion {

		log.info("Parametros Entrada [organoId]: " + organoId);
		log.info("Parametros Entrada [entidadId]: " + entidadId);
		log.info("Parametros Entrada [organo]: " + organo);
		log.info("Parametros Entrada [usuario]: " + usuario);
		log.info("Parametros Entrada [estadoRegistro]: " + estadoRegistro);
    	
		Session session = entityManager.unwrap(Session.class);
		final MensajeRespuesta mensajeRespuesta = new MensajeRespuesta();
		try {
			session.doWork(new Work() {
				@Override
				public void execute(Connection connection) throws SQLException {
					CallableStatement callableStatement = null;

					try {
						connection.setAutoCommit(false);
						callableStatement = connection.prepareCall(Constantes.SP_EDITAR_ORGANOS);
						callableStatement.setLong("E_ORGANO_ID",organoId);
						callableStatement.setLong("E_ENTIDAD_ID",entidadId);
						callableStatement.setString("E_ORGANO", organo);
						callableStatement.setString("E_USUARIO", usuario);
						callableStatement.setString("E_ESTADO_REGISTRO", estadoRegistro);
						
						callableStatement.registerOutParameter("S_ID_ERROR",OracleTypes.INTEGER);
						callableStatement.registerOutParameter("S_DES_ERROR",OracleTypes.VARCHAR);
						callableStatement.registerOutParameter("S_DES_ERROR_INFO",OracleTypes.VARCHAR);
						callableStatement.execute();
						
						log.info("Se ejecuto exitosamente el SP.");
						int codigoError = callableStatement.getInt("S_ID_ERROR");
						String mensajeError = callableStatement.getString("S_DES_ERROR");
						String mensajeErrorInfo = callableStatement.getString("S_DES_ERROR_INFO");
						
						log.info("Parametros Salida [codigoError]: " + codigoError);
						log.info("Parametros Salida [mensajeError]: " + mensajeError);

						mensajeRespuesta.setCodigoError(String.valueOf(codigoError));
						mensajeRespuesta.setMensajeError(mensajeError);
						
						if (callableStatement.getInt("S_ID_ERROR") == 1) {
							log.info("Se actualizo Organo con exito en BD.");
							connection.commit();
						} else if (callableStatement.getInt("S_ID_ERROR") == -1) {
							log.info("No se puede actualizar los datos en BD. " + mensajeError);
						} else {
							log.info("No se pudo actualizar los datos en BD. " + mensajeErrorInfo);
							throw new SQLException();
						}
						
					} catch(SQLException e){
						log.error("SQLException : ", e);
						connection.rollback();
						throw e;
					} catch (Exception e) {
						log.error("Exception : ", e);
						connection.rollback();
						throw e;
					}finally {
						Utilitario.cerrarCallableStatement(callableStatement);
					}
				}
			});
		} catch (Exception e) {
			if (mensajeRespuesta.getCodigoError() == null) {
				String mensajeError = consumirProcedimientoDAOLocal.consultarMensaje(Constantes.CODIGO_MSJ_ERROR_DB);
				throw new DAOExcepcion(Constantes.CODIGO_MSJ_ERROR_DB, mensajeError);
			}
			throw new DAOExcepcion(mensajeRespuesta.getCodigoError(), mensajeRespuesta.getMensajeError());
		}
			
			return mensajeRespuesta;
	}

}